﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Kokomo.Mirror.Ia32
{
	public static class Registers
	{
		static Registers()
		{
			AL = new Register(0, "AL", OperandSize.Byte, RegisterType.GeneralPurpose);
			CL = new Register(1, "CL", OperandSize.Byte, RegisterType.GeneralPurpose);
			DL = new Register(2, "DL", OperandSize.Byte, RegisterType.GeneralPurpose);
			BL = new Register(3, "BL", OperandSize.Byte, RegisterType.GeneralPurpose);
			AH = new Register(4, "AH", OperandSize.Byte, RegisterType.GeneralPurpose);
			CH = new Register(5, "CH", OperandSize.Byte, RegisterType.GeneralPurpose);
			DH = new Register(6, "DH", OperandSize.Byte, RegisterType.GeneralPurpose);
			BH = new Register(7, "BH", OperandSize.Byte, RegisterType.GeneralPurpose);

			AX = new Register(0, "AX", OperandSize.Word, RegisterType.GeneralPurpose);
			CX = new Register(1, "CX", OperandSize.Word, RegisterType.GeneralPurpose);
			DX = new Register(2, "DX", OperandSize.Word, RegisterType.GeneralPurpose);
			BX = new Register(3, "BX", OperandSize.Word, RegisterType.GeneralPurpose);
			SP = new Register(4, "SP", OperandSize.Word, RegisterType.GeneralPurpose);
			BP = new Register(5, "BP", OperandSize.Word, RegisterType.GeneralPurpose);
			SI = new Register(6, "SI", OperandSize.Word, RegisterType.GeneralPurpose);
			DI = new Register(7, "DI", OperandSize.Word, RegisterType.GeneralPurpose);

			EAX = new Register(0, "EAX", OperandSize.Dword, RegisterType.GeneralPurpose);
			ECX = new Register(1, "ECX", OperandSize.Dword, RegisterType.GeneralPurpose);
			EDX = new Register(2, "EDX", OperandSize.Dword, RegisterType.GeneralPurpose);
			EBX = new Register(3, "EBX", OperandSize.Dword, RegisterType.GeneralPurpose);
			ESP = new Register(4, "ESP", OperandSize.Dword, RegisterType.GeneralPurpose);
			EBP = new Register(5, "EBP", OperandSize.Dword, RegisterType.GeneralPurpose);
			ESI = new Register(6, "ESI", OperandSize.Dword, RegisterType.GeneralPurpose);
			EDI = new Register(7, "EDI", OperandSize.Dword, RegisterType.GeneralPurpose);

			RAX = new Register(0, "RAX", OperandSize.Qword, RegisterType.GeneralPurpose);
			RCX = new Register(1, "RCX", OperandSize.Qword, RegisterType.GeneralPurpose);
			RDX = new Register(2, "RDX", OperandSize.Qword, RegisterType.GeneralPurpose);
			RBX = new Register(3, "RBX", OperandSize.Qword, RegisterType.GeneralPurpose);
			RSP = new Register(4, "RSP", OperandSize.Qword, RegisterType.GeneralPurpose);
			RBP = new Register(5, "RBP", OperandSize.Qword, RegisterType.GeneralPurpose);
			RSI = new Register(6, "RSI", OperandSize.Qword, RegisterType.GeneralPurpose);
			RDI = new Register(7, "RDI", OperandSize.Qword, RegisterType.GeneralPurpose);

			R8D = new Register(08, "R8D", OperandSize.Dword, RegisterType.GeneralPurpose);
			R9D = new Register(09, "R9D", OperandSize.Dword, RegisterType.GeneralPurpose);
			R10D = new Register(10, "R10D", OperandSize.Dword, RegisterType.GeneralPurpose);
			R11D = new Register(11, "R11D", OperandSize.Dword, RegisterType.GeneralPurpose);
			R12D = new Register(12, "R12D", OperandSize.Dword, RegisterType.GeneralPurpose);
			R13D = new Register(13, "R13D", OperandSize.Dword, RegisterType.GeneralPurpose);
			R14D = new Register(14, "R14D", OperandSize.Dword, RegisterType.GeneralPurpose);
			R15D = new Register(15, "R15D", OperandSize.Dword, RegisterType.GeneralPurpose);

			R8 = new Register(08, "R8", OperandSize.Qword, RegisterType.GeneralPurpose);
			R9 = new Register(09, "R9", OperandSize.Qword, RegisterType.GeneralPurpose);
			R10 = new Register(10, "R10", OperandSize.Qword, RegisterType.GeneralPurpose);
			R11 = new Register(11, "R11", OperandSize.Qword, RegisterType.GeneralPurpose);
			R12 = new Register(12, "R12", OperandSize.Qword, RegisterType.GeneralPurpose);
			R13 = new Register(13, "R13", OperandSize.Qword, RegisterType.GeneralPurpose);
			R14 = new Register(14, "R14", OperandSize.Qword, RegisterType.GeneralPurpose);
			R15 = new Register(15, "R15", OperandSize.Qword, RegisterType.GeneralPurpose);

			MM0 = new Register(0, "MM0", OperandSize.Qword, RegisterType.Mmx);
			MM1 = new Register(1, "MM1", OperandSize.Qword, RegisterType.Mmx);
			MM2 = new Register(2, "MM2", OperandSize.Qword, RegisterType.Mmx);
			MM3 = new Register(3, "MM3", OperandSize.Qword, RegisterType.Mmx);
			MM4 = new Register(4, "MM4", OperandSize.Qword, RegisterType.Mmx);
			MM5 = new Register(5, "MM5", OperandSize.Qword, RegisterType.Mmx);
			MM6 = new Register(6, "MM6", OperandSize.Qword, RegisterType.Mmx);
			MM7 = new Register(7, "MM7", OperandSize.Qword, RegisterType.Mmx);

			ST0 = new Register(0, "ST0", OperandSize.Float80, RegisterType.Fpu);
			ST1 = new Register(1, "ST1", OperandSize.Float80, RegisterType.Fpu);
			ST2 = new Register(2, "ST2", OperandSize.Float80, RegisterType.Fpu);
			ST3 = new Register(3, "ST3", OperandSize.Float80, RegisterType.Fpu);
			ST4 = new Register(4, "ST4", OperandSize.Float80, RegisterType.Fpu);
			ST5 = new Register(5, "ST5", OperandSize.Float80, RegisterType.Fpu);
			ST6 = new Register(6, "ST6", OperandSize.Float80, RegisterType.Fpu);
			ST7 = new Register(7, "ST7", OperandSize.Float80, RegisterType.Fpu);

			XMM0 = new Register(0, "XMM0", OperandSize.Float128, RegisterType.Simd);
			XMM1 = new Register(1, "XMM1", OperandSize.Float128, RegisterType.Simd);
			XMM2 = new Register(2, "XMM2", OperandSize.Float128, RegisterType.Simd);
			XMM3 = new Register(3, "XMM3", OperandSize.Float128, RegisterType.Simd);
			XMM4 = new Register(4, "XMM4", OperandSize.Float128, RegisterType.Simd);
			XMM5 = new Register(5, "XMM5", OperandSize.Float128, RegisterType.Simd);
			XMM6 = new Register(6, "XMM6", OperandSize.Float128, RegisterType.Simd);
			XMM7 = new Register(7, "XMM7", OperandSize.Float128, RegisterType.Simd);

			EIP = new Register(-1, "EIP", OperandSize.Dword, RegisterType.Control);
			EFLAGS = new Register(-1, "EFLAGS", OperandSize.Dword, RegisterType.Control);

			CR0 = new Register(0, "CR0", OperandSize.Dword, RegisterType.Control);
			CR1 = new Register(1, "CR1", OperandSize.Dword, RegisterType.Control);
			CR2 = new Register(2, "CR2", OperandSize.Dword, RegisterType.Control);
			CR3 = new Register(3, "CR3", OperandSize.Dword, RegisterType.Control);
			CR4 = new Register(4, "CR4", OperandSize.Dword, RegisterType.Control);
			CR5 = new Register(5, "CR5", OperandSize.Dword, RegisterType.Control);
			CR6 = new Register(6, "CR6", OperandSize.Dword, RegisterType.Control);
			CR7 = new Register(7, "CR7", OperandSize.Dword, RegisterType.Control);

			DR0 = new Register(0, "DR0", OperandSize.Dword, RegisterType.Debug);
			DR1 = new Register(1, "DR1", OperandSize.Dword, RegisterType.Debug);
			DR2 = new Register(2, "DR2", OperandSize.Dword, RegisterType.Debug);
			DR3 = new Register(3, "DR3", OperandSize.Dword, RegisterType.Debug);
			DR4 = new Register(4, "DR4", OperandSize.Dword, RegisterType.Debug);
			DR5 = new Register(5, "DR5", OperandSize.Dword, RegisterType.Debug);
			DR6 = new Register(6, "DR6", OperandSize.Dword, RegisterType.Debug);
			DR7 = new Register(7, "DR7", OperandSize.Dword, RegisterType.Debug);

			ES = new Register(0, "ES", OperandSize.Word, RegisterType.Segment);
			CS = new Register(1, "CS", OperandSize.Word, RegisterType.Segment);
			SS = new Register(2, "SS", OperandSize.Word, RegisterType.Segment);
			DS = new Register(3, "DS", OperandSize.Word, RegisterType.Segment);
			FS = new Register(4, "FS", OperandSize.Word, RegisterType.Segment);
			GS = new Register(5, "GS", OperandSize.Word, RegisterType.Segment);

			_registers = new Register[] {
				AL,   CL,   DL,   BL,   AH,   CH,   DH,   BH,
				AX,   BX,   CX,   DX,   SP,   BP,   SI,   DI,
				EAX,  EBX,  ECX,  EDX,  ESP,  EBP,  ESI,  EDI,
				RAX,  RBX,  RCX,  RDX,  RSP,  RBP,  RSI,  RDI,
				R8,   R9,   R10,  R11,  R12,  R13,  R14,  R15,
				R8D,  R9D,  R10D, R11D, R12D, R13D, R14D, R15D,
				MM0,  MM1,  MM2,  MM3,  MM4,  MM5,  MM6,  MM7,
				ST0,  ST1,  ST2,  ST3,  ST4,  ST5,  ST6,  ST7,
				ST0,  ST1,  ST2,  ST3,  ST4,  ST5,  ST6,  ST7,
				XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7,
				CR0,  CR1,  CR2,  CR3,  CR4,  CR5,  CR6,  CR7,
				DR0,  DR1,  DR2,  DR3,  DR4,  DR5,  DR6,  DR7,
				ES,   CS,   SS,   DS,   FS,   GS
			};
		}

		#region General-purpose
		public static readonly Register AL;
		public static readonly Register CL;
		public static readonly Register DL;
		public static readonly Register BL;
		public static readonly Register AH;
		public static readonly Register CH;
		public static readonly Register DH;
		public static readonly Register BH;

		public static readonly Register AX;
		public static readonly Register BX;
		public static readonly Register CX;
		public static readonly Register DX;
		public static readonly Register SP;
		public static readonly Register BP;
		public static readonly Register SI;
		public static readonly Register DI;

		public static readonly Register EAX;
		public static readonly Register EBX;
		public static readonly Register ECX;
		public static readonly Register EDX;
		public static readonly Register ESP;
		public static readonly Register EBP;
		public static readonly Register ESI;
		public static readonly Register EDI;

		public static readonly Register RAX;
		public static readonly Register RBX;
		public static readonly Register RCX;
		public static readonly Register RDX;
		public static readonly Register RSP;
		public static readonly Register RBP;
		public static readonly Register RSI;
		public static readonly Register RDI;

		public static readonly Register R8;
		public static readonly Register R9;
		public static readonly Register R10;
		public static readonly Register R11;
		public static readonly Register R12;
		public static readonly Register R13;
		public static readonly Register R14;
		public static readonly Register R15;

		public static readonly Register R8D;
		public static readonly Register R9D;
		public static readonly Register R10D;
		public static readonly Register R11D;
		public static readonly Register R12D;
		public static readonly Register R13D;
		public static readonly Register R14D;
		public static readonly Register R15D;
		#endregion
		#region MMX
		public static readonly Register MM0;
		public static readonly Register MM1;
		public static readonly Register MM2;
		public static readonly Register MM3;
		public static readonly Register MM4;
		public static readonly Register MM5;
		public static readonly Register MM6;
		public static readonly Register MM7;
		#endregion
		#region FPU
		public static readonly Register ST0;
		public static readonly Register ST1;
		public static readonly Register ST2;
		public static readonly Register ST3;
		public static readonly Register ST4;
		public static readonly Register ST5;
		public static readonly Register ST6;
		public static readonly Register ST7;
		#endregion
		#region SIMD
		public static readonly Register XMM0;
		public static readonly Register XMM1;
		public static readonly Register XMM2;
		public static readonly Register XMM3;
		public static readonly Register XMM4;
		public static readonly Register XMM5;
		public static readonly Register XMM6;
		public static readonly Register XMM7;
		#endregion
		#region Segment registers
		public static readonly Register ES;
		public static readonly Register CS;
		public static readonly Register SS;
		public static readonly Register DS;
		public static readonly Register FS;
		public static readonly Register GS;
		#endregion
		#region Control registers
		public static readonly Register EIP;
		public static readonly Register EFLAGS;

		public static readonly Register CR0;
		public static readonly Register CR1;
		public static readonly Register CR2;
		public static readonly Register CR3;
		public static readonly Register CR4;
		public static readonly Register CR5;
		public static readonly Register CR6;
		public static readonly Register CR7;
		#endregion
		#region Debug registers
		public static readonly Register DR0;
		public static readonly Register DR1;
		public static readonly Register DR2;
		public static readonly Register DR3;
		public static readonly Register DR4;
		public static readonly Register DR5;
		public static readonly Register DR6;
		public static readonly Register DR7;
		#endregion

		internal static Register[] _registers;
	}
}
